/**
 *     This file is part of cesm-ws.
 *
 *     cesm-ws, Web Service for Community Earth System Model
 *
 *     Copyright (c) 2010, Purdue University and/or affilicates or thrid-party contributors as
 *     indicated by the @author tags or express copyright attribution statements
 *     applied by the authors. All third-party contributions are distributed under
 *     license by Purdue University.
 *
 *     cesm-ws is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this distribution.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.purdue.rcac.cesm.persistence.model;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import edu.purdue.rcac.cesm.define.Machine;
import edu.purdue.rcac.cesm.define.ComponentSet;
import edu.purdue.rcac.cesm.define.Resolution;

@Entity
@Table(name = "CESM_CASE_CONFIG")
@NamedQueries({
		@NamedQuery(name = CESMCaseConfig.FIND_BY_ID, query = "SELECT c FROM CESMCaseConfig c WHERE c.id=:id"),
		@NamedQuery(name = CESMCaseConfig.FIND_BY_OWNER_N_NAME, query = "SELECT c FROM CESMCaseConfig c WHERE c.owner=:owner AND c.name=:name"),
		@NamedQuery(name = CESMCaseConfig.FIND_BY_OWNER, query = "SELECT c FROM CESMCaseConfig c WHERE c.owner=:owner"),
		@NamedQuery(name = CESMCaseConfig.FIND_ALL_RUNNING, query = "SELECT c from CESMCaseConfig c WHERE c.stage='RUNNING'") })
public class CESMCaseConfig {
	/**
	 * public static fields
	 */
	public static final String FIND_BY_ID = "find_case_config_by_id";
	public static final String FIND_BY_OWNER_N_NAME = "find_case_config_by_owner_and_name";
	public static final String FIND_BY_OWNER = "find_case_config_by_owner";
	public static final String FIND_ALL_RUNNING = "find_case_config_with_running_stage";

	public static enum CaseStage {
		NONE, CREATED, CONFIGURED, RUNNING, CANCELLED, DELETED,
		// all caseRuntime completes
		DONE,
		// job ran successfully
		SUCCESS,
		// job failed
		FAILED
	}

	public static enum AccessLevel {
		PUBLIC, PRIVATE
	};

	/**
	 * Fields
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@OneToMany(mappedBy = "caseConfig", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private List<CESMCaseRuntime> runtimes;

	private String owner;
	private String name;
	private String startDate;
	private String duration;
	private String endDate;
	private int resubmit;
	private Timestamp creationTime;

	@Enumerated(EnumType.STRING)
	private Machine machine;

	@Enumerated(EnumType.STRING)
	private Resolution resolution;

	@Enumerated(EnumType.STRING)
	private ComponentSet componentSet;

	@Enumerated(EnumType.STRING)
	private AccessLevel accessLevel;

	@Enumerated(EnumType.STRING)
	private CaseStage stage;

	/**
	 * Constructor
	 */
	public CESMCaseConfig(String userName, String caseName,
			Resolution resolution, ComponentSet componentSet) {
		this();
		this.owner = userName;
		this.name = caseName;
		this.resolution = resolution;
		this.componentSet = componentSet;

	}

	public CESMCaseConfig() {
		super();
		this.stage = CaseStage.NONE;
		this.accessLevel = AccessLevel.PUBLIC;
		this.creationTime = new Timestamp(new Date().getTime());
		this.duration = "5:ndays";
		this.startDate = "0001-01-01";
		this.endDate = "0001-01-06";
		this.runtimes = new ArrayList<CESMCaseRuntime>();
	}

	/**
	 * Getters & Setters
	 */

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Resolution getResolution() {
		return resolution;
	}

	public void setResolution(Resolution resolution) {
		this.resolution = resolution;
	}

	public ComponentSet getComponentSet() {
		return componentSet;
	}

	public void setComponentSet(ComponentSet componentSet) {
		this.componentSet = componentSet;
	}

	public String getDuration() {
		return duration;
	}

	public void setDuration(String duration) {
		this.duration = duration;
	}

	public AccessLevel getAccessLevel() {
		return accessLevel;
	}

	public void setAccessLevel(AccessLevel accessLevel) {
		this.accessLevel = accessLevel;
	}

	public String getOwner() {
		return owner;
	}

	public void setOwner(String owner) {
		this.owner = owner;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<CESMCaseRuntime> getRuntimes() {
		if (runtimes == null) {
			runtimes = new ArrayList<CESMCaseRuntime>();
		}
		return runtimes;
	}

	public void setRuntimes(List<CESMCaseRuntime> runtimes) {
		this.runtimes = runtimes;
	}

	public CaseStage getStage() {
		return stage;
	}

	public void setStage(CaseStage stage) {
		this.stage = stage;
	}

	public int getResubmit() {
		return resubmit;
	}

	public void setResubmit(int resubmit) {
		this.resubmit = resubmit;
	}

	public Timestamp getCreationTime() {
		return creationTime;
	}

	public void setCreationTime(Timestamp creationTime) {
		this.creationTime = creationTime;
	}

	public String getStartDate() {
		return startDate;
	}

	public void setStartDate(String startDate) {
		this.startDate = startDate;
	}

	public String getEndDate() {
		return endDate;
	}

	public void setEndDate(String endDate) {
		this.endDate = endDate;
	}

	public Machine getMachine() {
		return machine;
	}

	public void setMachine(Machine machine) {
		this.machine = machine;
	}

	@Override
	public String toString() {
		return String.format("<CESMCaseConfig>\n\t" + "id           = %d\n\t"
				+ "name         = %s\n\t" + "owner        = %s\n\t"
				+ "accessLevel  = %s\n\t" + "resubmit     = %d\n\t"
				+ "resolution   = %s\n\t" + "componentSet = %s\n\t"
				+ "startDate    = %s\n\t" + "endDate      = %s\n\t"
				+ "duration     = %s\n", id, name, owner,
				accessLevel.toString(), resubmit, resolution.toString(),
				componentSet.toString(), startDate.toString(),
				endDate.toString(), duration);
	}

	public String toShort() {
		return String.format("<CESMCaseConfig> id=%d, name=%s, owner=%s\n", id,
				name, owner);
	}

}
